/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.store.client.components;

import java.util.HashMap;
import java.util.List;

import com.elf.gwt.common.client.model.CategoryMetaModel;
import com.elf.gwt.common.client.model.CategoryModel;
import com.elf.gwt.store.client.StoreComponentController;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;


/**
 *
 */
public class CategoriesComponent extends JSONServerComponent
{	
	protected int currentCategoryId = -1;
	protected int currentManufacturingId = -1;
	protected CategoryMetaModel categoryMetaModel;
	protected CategoryModel categoryModel;
	protected CategoryModel rootCategoryModel = null;
	protected HashMap<String, CategoryModel> categoriesHash;
	protected HashMap<String, TreeItem> treeHash;
	public Tree tree;

	/**
	 * Constructor
	 */
	public CategoriesComponent(StoreComponentController controller, String stylePrefix)
	{
		super(controller, stylePrefix, null, false);
		panel.getCellFormatter().addStyleName(1, 0, getHandle() + "Tree");
		categoriesHash = new HashMap<String, CategoryModel>();
		treeHash = new HashMap<String, TreeItem>();
		categoryModel = new CategoryModel();
	}

	protected void buildMetaModel(JSONObject jsonObject) throws Exception
	{
		categoryMetaModel = new CategoryMetaModel(jsonObject);
	}

	protected void buildModel(JSONArray jsonArray) throws Exception
	{
		currentCategoryId = -1;
		currentManufacturingId = -1;
		categoriesHash.clear();
		treeHash.clear();
		if (rootCategoryModel == null) rootCategoryModel = new CategoryModel(0, categoryMetaModel.getStoreName(), "", null, 0, null, 0, categoryMetaModel.getCategoriesPerRowMax(), categoryMetaModel.isHideEmptyCategories());
		rootCategoryModel.getChildList().clear();
		categoriesHash.put("0", rootCategoryModel);
		if (categoryModel.getId() == 0) categoryModel.update(rootCategoryModel);

		int sz = jsonArray.size();

		for (int i = 0; i < sz; i++)
		{
			JSONValue jsonValue = jsonArray.get(i);
			JSONObject jsonObject;
			if ((jsonObject = jsonValue.isObject()) != null)
			{
				CategoryModel model = new CategoryModel(jsonObject, categoryMetaModel);
				CategoryModel pmodel = getCategoryModel(model.getParentId());
				model.setParentModel(pmodel);
				categoriesHash.put(String.valueOf(model.getId()), model);
								
				if (pmodel != null)
				{
					List<CategoryModel> lst = pmodel.getChildList();
					boolean match = false;
					for (int j = 0; j< lst.size(); j++)
					{
						CategoryModel cmodel = lst.get(j);
						if (model.getId() == cmodel.getId())
						{
							match = true;
							break;
						}
					}
					if (!match && pmodel.getId() != model.getId())	pmodel.getChildList().add(model);					
				}
			}
		}
	}

	public void buildFromModel() throws Exception
	{
		TreeItem root = new TreeItem(categoryMetaModel.getStoreName());
		root.addStyleName("ComponentLink");
		root.addStyleName(getHandle() + "Link");
		root.setUserObject("0");
		int count = addTreeItems(getCategoryModel(0), root);
		CategoryModel hashModel = getCategoryModel(0);
		hashModel.setCount(count);
		treeHash.put("0", root);
		tree = new Tree();
		root.setState(true);
		tree.addItem(root);

		tree.addSelectionHandler(treeHandler);

		panel.setWidget(1, 0, tree);

		int id = categoryMetaModel.getCurrentId();
		categoryModel.update(getCategoryModel(id));

		displaySelectionWithCallback();
	}

	/**
	 * @param parentId
	 * @param parent
	 */
	protected int addTreeItems(CategoryModel pmodel, TreeItem parent)
	{
		int sz = pmodel.getChildList().size();
		int totalCount = 0;
		for (int i = 0; i < sz; i++)
		{
			CategoryModel cmodel = pmodel.getChildList().get(i);
			int count = cmodel.getCount();
			TreeItem child= new TreeItem(cmodel.getName());
			child.setHTML("<span>" + cmodel.getName() + "</span>");

			int childCount = addTreeItems(cmodel,child);
			if (count == 0)
			{
				count = childCount;
			}
			cmodel.setCount(count);

			if (categoryMetaModel.isShowCounts()) child.setHTML("<span>" + cmodel.getName() + "</span> <span class=\"" + getHandle() + "Count\">(" + count + ")</span>");

			child.setUserObject(String.valueOf(cmodel.getId()));
			child.addStyleName("ComponentLink");
			child.addStyleName(getHandle() + "Link");

			if (count > 0 || !categoryMetaModel.isHideEmptyCategories()) parent.addItem(child);

			treeHash.put(String.valueOf(cmodel.getId()), child);
			totalCount = totalCount + count;
		}
		return totalCount;
	}

	protected void setTreeStatus(TreeItem treeItem, boolean status)
	{
		TreeItem parent = null;
		try {
			parent = treeItem.getParentItem();
		}
		catch (Exception e){}
		if (parent != null)
		{
			parent.setState(status);
			setTreeStatus(parent, status);
		}

	}

	public void displaySelectionWithCallback()
	{
		int id = categoryModel.getId();
		int mid = StoreComponentController.manufacturersComponent.getManufacturerModel().getId();
		if (id != currentCategoryId || mid != currentManufacturingId)
		{
			//displaySelection();	
			currentCategoryId = id;
			currentManufacturingId = mid;
			
			onBuilt();
		}
	}

	public void displaySelection()
	{
		if (tree != null)
		{
			int id = categoryModel.getId();
			TreeItem treeItem = treeHash.get(String.valueOf(id));
			tree.setSelectedItem(treeItem, false);
			tree.ensureSelectedItemVisible();
		}
	}

	public void collapseTree()
	{
		TreeItem treeItem = treeHash.get("0");
		int sz = treeItem.getChildCount();
		for (int i = 0; i < sz; i++)
		{
			collapseTree(treeItem.getChild(i));
		}
	}

	protected void collapseTree(TreeItem treeItem)
	{
		int sz = treeItem.getChildCount();
		for (int i = 0; i < sz; i++)
		{
			collapseTree(treeItem.getChild(i));
		}
		if (sz > 0 && treeItem.getState()) treeItem.setState(false, false);
	}

	protected SelectionHandler<TreeItem> treeHandler = new SelectionHandler<TreeItem>() {
		public void onSelection(SelectionEvent<TreeItem> event) {
			TreeItem item = (TreeItem)event.getSelectedItem();
			String strId = (String)item.getUserObject();
			CategoryModel model = categoriesHash.get(strId);
			
			if (model.getChildList().size() == 0 && model.getCount() > 0)
			{
				thisComponent.onSelection("AdvancedSearchResultsComponent--" + model.getId() 
						+ "--" + StoreComponentController.manufacturersComponent.getManufacturerModel().getId() + "--false--false--false--0--0--*--*--0--*--*");
			}
			else
			{
				thisComponent.onSelection("CategoriesSummaryComponent--" + model.getId());
			}
			
		}
	};

	public CategoryModel getCategoryModel(int id) {
		return categoriesHash.get(String.valueOf(id));
	}

	public CategoryModel getCategoryModel() {
		return categoryModel;
	}
}
